package com.xbongbong.paas.service.workflow.comment.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.formula.constant.Constant;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.thread.LogThreadPoolBeanConfig;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowCommentAddDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowCommentDeleteDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowCommentEditDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowCommentListDTO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowCommentAddVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowCommentDeleteVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowCommentListVO;
import com.xbongbong.paas.service.workflow.comment.WorkflowCommentPushMsgService;
import com.xbongbong.paas.service.workflow.comment.WorkflowCommentService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.CommentHelp;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.log.enums.DetailLogEnum;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowCommentEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowCommentEntityExt;
import com.xbongbong.workflow.model.WorkflowCommentModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author chenpeng
 * @version 1.0
 * @date 2021-05-11 15:51
 * @description
 */
@Service
@Slf4j
public class WorkflowCommentServiceImpl implements WorkflowCommentService {

    @Resource
    private WorkflowCommentModel workflowCommentModel;

    @Resource
    private UserModel userModel;
    @Resource
    private WorkflowCommentPushMsgService workflowCommentPushMsgService;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private LogThreadPoolBeanConfig logThreadPoolBeanConfig;

    @Override
    public WorkflowCommentListVO list(WorkflowCommentListDTO commentListDTO) throws XbbException {
        WorkflowCommentListVO commentListVO = new WorkflowCommentListVO();
        Map<String, Object> map = BeanUtil.convertBean2Map(commentListDTO, true);
        map.put(ParameterConstant.ORDER_BY_STR, " add_time desc");
        try {
            //查询新的评论表
            List<WorkflowCommentEntityExt> list = workflowCommentModel.findEntities(map);
            if (list == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            
            List<WorkflowCommentEntityExt> arrayList = new ArrayList<>();
            //过滤出AtUserId集合
            Set<String> collect = new HashSet<>();
            list.stream().map(v -> JSONArray.parseArray(v.getAtUserId(), String.class)).forEach(collect::addAll);
            //查询头像信息
            List<UserEntity> entityList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(collect)) {
                entityList = userModel.getByUserIdIn(commentListDTO.getCorpid(), new ArrayList<>(collect), true);
            }
            Map<String, UserEntity> userEntityMap = new HashMap<>();
            entityList.forEach(v -> userEntityMap.put(v.getUserId(), v));

            boolean adminOrBoss = commentListDTO.getLoginUser().isAdminOrBoss();

            for (WorkflowCommentEntityExt item : list) {
                List<String> strings = JSONArray.parseArray(item.getAtUserId(), String.class);
                JSONArray jsonArray = new JSONArray();
                strings.forEach(v -> {
                    UserEntity userEntity = userEntityMap.get(v);
                    if (Objects.nonNull(userEntity)) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put(ParameterConstant.AVATAR, userEntity.getAvatar());
                        jsonObject.put(ParameterConstant.ID, userEntity.getUserId());
                        jsonObject.put(ParameterConstant.NAME, userEntity.getName());
                        jsonArray.add(jsonObject);
                    }
                });
                item.setAtUserIdList(jsonArray);
                item.setAddTimeStr(DateTimeUtil.getStringEpochSecond(item.getAddTime(), DateTimeUtil.SDF));
                JSONArray perJsonarray = new JSONArray();
                if (adminOrBoss || Objects.equals(commentListDTO.getUserId(), item.getUserId())) {
                    perJsonarray.add("delete");
                    perJsonarray.add("edit");
                }
                item.setPermissionSet(perJsonarray);

                arrayList.add(item);
            }


            commentListVO.setList(arrayList);
            commentListVO.setCommentCount(arrayList.size());
            
        } catch (Exception e) {
            log.error("工作流评论list()出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commentListVO;
    }
    
    @Override
    public WorkflowCommentAddVO add(WorkflowCommentAddDTO commentAddDTO) throws XbbException {
        WorkflowCommentAddVO commentAddVO = new WorkflowCommentAddVO();
        
        List<String> targetUserId = Collections.singletonList(commentAddDTO.getUserId());
        UserVO loginUser = commentAddDTO.getLoginUser();
        String corpid = commentAddDTO.getCorpid();
        if (StringUtil.isNotEmpty(commentAddDTO.getRefUserId())) {
            targetUserId.add(commentAddDTO.getRefUserId());
        }
        
        try {
            //查询userid和refuserid是否存在
            List<UserEntity> userEntityList = userModel.getByUserId(targetUserId, commentAddDTO.getCorpid());
            if (CollectionUtils.isEmpty(userEntityList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            //转成map
            Map<String, UserEntity> entityMap = userEntityList.stream().collect(Collectors.toMap(UserEntity::getUserId, t -> t));
            //处理引用的userid
            WorkflowCommentEntity workflowCommentEntity = new WorkflowCommentEntity();
            BeanUtils.copyProperties(commentAddDTO, workflowCommentEntity);
            UserEntity userEntity = entityMap.get(commentAddDTO.getUserId());
            workflowCommentEntity.setUserName(userEntity.getName());
            workflowCommentEntity.setUserAvatar(userEntity.getAvatar());
            
            Optional.of(entityMap)
                    .map(t -> t.get(commentAddDTO.getRefUserId()))
                    .map(UserEntity::getName)
                    .ifPresent(workflowCommentEntity::setRefUserName);
            
            //@的userid
            List<String> atUserIds = commentAddDTO.getAtUserIds();
            workflowCommentEntity.setAtUserId(JSON.toJSONString(atUserIds));
            workflowCommentEntity.setRefId(commentAddDTO.getRefId());
            workflowCommentEntity.setImage(JSON.toJSONString(commentAddDTO.getImages()));
            workflowCommentEntity.setAttachment(JSON.toJSONString(commentAddDTO.getAttachmentList()));
            workflowCommentEntity.setDel(DelEnum.NORMAL.getDel());
            workflowCommentModel.insert(workflowCommentEntity);
            commentAddVO.setCommentId(workflowCommentEntity.getId());
        } catch (Exception e) {
            log.error("工作流评论add()出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        Runnable runnable = () -> {

            try{
                // 评论/艾特消息推送
                workflowCommentPushMsgService.pushComment(commentAddDTO.getLoginUser(), BusinessCommentEnum.APPROVAL.getBusinessType(), commentAddDTO.getRefId(), commentAddDTO.getCorpid(), commentAddDTO.getAtUserIds(), CommentHelp.filterCommentContent(commentAddDTO.getContent()), BusinessCommentEnum.APPROVAL, commentAddDTO.getIsInform());

                //日志
                DetailLogPojo detailLogPojo = new DetailLogPojo();
                detailLogPojo.setContentText(commentAddDTO.getContent());
                detailLogPojo.setPictureCount(commentAddDTO.getImages().size());
                detailLogPojo.setAttachmentCount(commentAddDTO.getAttachmentList().size());
                WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(commentAddDTO.getRefId(), corpid);
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(ParameterConstant.CORPID,corpid);
                param.put("taskId",workflowTaskEntity.getId());
                param.put(ParameterConstant.DEL,DelEnum.NORMAL);
                List<WorkflowTaskNodeEntity> workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(param);
                String title = workflowTaskNodeEntities.get(Constant.ZERO).getTitle();
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_WORKFLOW_COMMENT), loginUser.getName());
                mongoLogHelp.buildLog4DetailArrWithComplexDetail(Collections.singletonList(detailLogPojo),commentAddDTO.getCorpid(),loginUser.getUserId(),loginUser.getName(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.CREATE_APPROVE_COMMENT,null,title,memo,commentAddDTO.getHttpHeader(),BasicConstant.THREE);

            }catch (Exception e){
                log.error("com.xbongbong.workflow.service.comment.impl.WorkflowCommentServiceImpl.add() log error");
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);

        return commentAddVO;
    }
    
    @Override
    public Integer getCount(String corpid, Integer businessType, Long appId, Long refId) {
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(ParameterConstant.CORPID, corpid);
        map.put(ParameterConstant.APPID, appId);
        map.put(ParameterConstant.TYPE, businessType);
        map.put(ParameterConstant.REF_ID, refId);
        map.put(ParameterConstant.DEL, 0);
        return workflowCommentModel.getEntityCount(map);
    }
    
    @Override
    public WorkflowCommentDeleteVO delete(WorkflowCommentDeleteDTO commentDeleteDTO) throws XbbException {
        WorkflowCommentDeleteVO commentDeleteVO = new WorkflowCommentDeleteVO();
        UserVO loginUser = commentDeleteDTO.getLoginUser();
        String corpid = commentDeleteDTO.getCorpid();
        //查询要删除的评论
        WorkflowCommentEntity entity = workflowCommentModel.getByKey(commentDeleteDTO.getCommentId(), commentDeleteDTO.getCorpid());
        try {
            if (entity == null) {
                return commentDeleteVO;
            }
            //更新目标
            entity.setDel(BasicConstant.ONE);
            workflowCommentModel.update(entity);
            commentDeleteVO.setCommentId(commentDeleteDTO.getCommentId());
        } catch (Exception e) {
            log.error("工作流评论delete()出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        Runnable runnable = () -> {

            try{
                // 评论删除消息推送
                workflowCommentPushMsgService.pushCommentDelete(commentDeleteDTO.getLoginUser(), BusinessCommentEnum.APPROVAL.getBusinessType(), commentDeleteDTO.getRefId(), commentDeleteDTO.getCorpid(), CommentHelp.filterCommentContent(entity.getContent()), BusinessCommentEnum.APPROVAL);

                JSONArray imageArray = JSONArray.parseArray(entity.getImage());
                int pictureCount = Objects.nonNull(imageArray) ? imageArray.size() : 0;
                JSONArray attachmentArray = JSONArray.parseArray(entity.getAttachment());
                int attachmentCount = Objects.nonNull(attachmentArray) ? attachmentArray.size() : 0;
                //日志
                DetailLogPojo detailLogPojo = new DetailLogPojo();
                detailLogPojo.setContentText(entity.getContent());
                detailLogPojo.setPictureCount(pictureCount);
                detailLogPojo.setAttachmentCount(attachmentCount);
                WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(commentDeleteDTO.getRefId(), corpid);
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(ParameterConstant.CORPID,corpid);
                param.put("taskId",workflowTaskEntity.getId());
                param.put(ParameterConstant.DEL,DelEnum.NORMAL);
                List<WorkflowTaskNodeEntity> workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(param);
                String title = workflowTaskNodeEntities.get(Constant.ZERO).getTitle();
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DEL_WORKFLOW_COMMENT), loginUser.getName());
                mongoLogHelp.buildLog4DetailArrWithComplexDetail(Collections.singletonList(detailLogPojo),corpid,loginUser.getUserId(),loginUser.getName(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.DEL_APPROVE_COMMENT,null,title,memo,commentDeleteDTO.getHttpHeader(),BasicConstant.THREE);

            }catch (Exception e){
                log.error("com.xbongbong.workflow.service.comment.impl.WorkflowCommentServiceImpl.delete() log error");
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);

        return commentDeleteVO;
    }
    
    @Override
    public WorkflowCommentAddVO edit(WorkflowCommentEditDTO commentEditDTO) throws XbbException {
        WorkflowCommentAddVO commentAddVO = new WorkflowCommentAddVO();
        String corpid = commentEditDTO.getCorpid();
        UserVO loginUser = commentEditDTO.getLoginUser();
        //查询要编辑的
        WorkflowCommentEntity entity = workflowCommentModel.getByKey(commentEditDTO.getCommentId(), commentEditDTO.getCorpid());

        //记录编辑前的内容、图片、附件
        String oldContent = entity.getContent();
        JSONArray imageArray = JSONArray.parseArray(entity.getImage());
        int oldPicCount = Objects.nonNull(imageArray) ? imageArray.size() : 0;
        JSONArray attachmentArray = JSONArray.parseArray(entity.getAttachment());
        int oldAttaCount = Objects.nonNull(attachmentArray) ? attachmentArray.size() : 0;

        try {

            if (null == entity) {
                return commentAddVO;
            }
            
            List<String> atUserIds = commentEditDTO.getAtUserIds();
            entity.setAtUserId(JSON.toJSONString(atUserIds));
            entity.setContent(commentEditDTO.getContent());
            entity.setImage(JSON.toJSONString(commentEditDTO.getImages()));
            entity.setAttachment(JSON.toJSONString(commentEditDTO.getAttachmentList()));
            workflowCommentModel.update(entity);

            commentAddVO.setCommentId(entity.getId());


        } catch (Exception e) {
            log.error("工作流评论edit()出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        Runnable runnable = () -> {

            try{
                // 评论/艾特消息推送
                workflowCommentPushMsgService.pushCommentEdit(commentEditDTO.getLoginUser(), BusinessCommentEnum.APPROVAL.getBusinessType(), commentEditDTO.getRefId(), commentEditDTO.getCorpid(), commentEditDTO.getAtUserIds(), CommentHelp.filterCommentContent(commentEditDTO.getContent()), BusinessCommentEnum.APPROVAL);

                //编辑后的内容、图片、附件
                String newContent = commentEditDTO.getContent();
                int newPicCount = commentEditDTO.getImages().size();
                int newAttaCount = commentEditDTO.getAttachmentList().size();
                List<DetailLogPojo> detailArr = new ArrayList<>();
                DetailLogPojo contentDetailLogPojo = new DetailLogPojo(null, DetailLogEnum.CONTENT_TEXT.getName(), oldContent, newContent);
                detailArr.add(contentDetailLogPojo);
                DetailLogPojo picDetailLogPojo = new DetailLogPojo(null, DetailLogEnum.PICTURE_COUNT.getName(), String.valueOf(oldPicCount), String.valueOf(newPicCount));
                detailArr.add(picDetailLogPojo);
                DetailLogPojo attaDetailLogPojo = new DetailLogPojo(null, DetailLogEnum.ATTACHMENT_COUNT.getName(), String.valueOf(oldAttaCount), String.valueOf(newAttaCount));
                detailArr.add(attaDetailLogPojo);

                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(ParameterConstant.CORPID,corpid);
                param.put("taskId",commentEditDTO.getRefId());
                param.put(ParameterConstant.DEL,DelEnum.NORMAL);
                List<WorkflowTaskNodeEntity> workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(param);
                String title = workflowTaskNodeEntities.get(Constant.ZERO).getTitle();
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_EDIT_WORKFLOW_COMMENT), loginUser.getName());
                mongoLogHelp.buildLog4DetailArr(detailArr, corpid, loginUser.getUserId(), loginUser.getName(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.EDIT_APPROVE_COMMENT,null, title, memo, commentEditDTO.getHttpHeader());
            }catch (Exception e){
                log.error("com.xbongbong.workflow.service.comment.impl.WorkflowCommentServiceImpl.edit() log error");
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);

        return commentAddVO;
    }
}
